package com.springsource.a04commonBeanPostProcessor;

import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

// AutowiredAnnotationBeanPostProcessor运行分析
public class DigInAutowired {

    public static void main(String[] args) throws Throwable {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("bean2", new Bean2()); // 直接注册的是成品bean，忽略创建过程、依赖注入、初始化
        beanFactory.registerSingleton("bean3", new Bean3());
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); //解析@Value注解
        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders);

        // 1、查找哪些属性、方法加了Autowired， 这称之为InjectionMetadata
        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(beanFactory);

        Bean1 bean1 = new Bean1();
        System.out.println("bean1: " + bean1);
        // 执行依赖注入，Autowired、Value
        // 第一个参数 pvs 是指不用自动装配的形式，手动指定的属性值
//        processor.postProcessProperties(null, bean1, "bean1");
        // postProcessProperties方法中，先调用findAutowiringMetadata方法，获取InjectionMetadata
        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(processor, "bean1", Bean1.class, null);
        // 2、调用InjectionMetadata的inject方法，执行依赖注入
        metadata.inject(bean1, "bean1", null);
        System.out.println("bean1: " + bean1);

        // 3、如何按类型查找值
        // 成员变量的情况
        Field bean3 = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor descriptorBean3 = new DependencyDescriptor(bean3, true);
        Object o = beanFactory.doResolveDependency(descriptorBean3, null, null, null);
        System.out.println("bean3: " + o);
        // 方法的情况，descriptor的构造是对应方法的第几个参数，描述了对哪个方法的哪个参数进行注入
        Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
        DependencyDescriptor descriptorBean2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), true);
        Object o1 = beanFactory.doResolveDependency(descriptorBean2, null, null, null);
        System.out.println("bean2: " + o1);

    }


}
